import pygtk
pygtk.require('2.0')
import gtk 
from time import * 
import threading
from threading import * 
from Queue import *  
import socket
global sock


HOST = '86.107.105.252'
PORT = 39883

class MyWnd:
	def ass(self, widget, event, data=None):
        	print "delete event occurred"
		return False
            
	def destroy(self, widget, data=None):
        	print "destroy signal occurred"
        	self.comm.stop()
        	gtk.main_quit()
		
		
	

	def __init__(self):
		self.comm = None
		#bagi aici codu de initializare a ferestrelor
		self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
	        self.vpaned = gtk.VPaned()
	        self.hpaned = gtk.HPaned()
	        self.entry1 = gtk.Entry()   
	        self.text =  gtk.TextView()
	        self.bufer = self.text.get_buffer()
	        self.button = gtk.Button("Send")
	        self.scrollwin = gtk.ScrolledWindow()


	        #connect window events
	        self.window.connect("delete_event", self.ass)
	        self.window.connect("destroy", self.destroy)
	        self.button.connect("clicked", self.click_handler, None)
	        self.entry1.connect("activate",self.click_handler, None)
                       
                        

                        

	        #combine elements
	        self.vpaned.pack1(self.scrollwin, True, False)
	        self.vpaned.pack2(self.hpaned, False, False)
	        self.hpaned.pack1(self.entry1, True, False)
	        self.hpaned.pack2(self.button, False, False)
	        self.scrollwin.add(self.text)


	        #configure elements
	        self.window.set_title("betachat")
	        self.window.set_border_width(5)
	        self.window.set_default_size(500,300)
	        self.window.add(self.vpaned)
	        self.text.set_wrap_mode(True) 
	        self.text.set_editable(False)  
	        self.text.set_overwrite(False) 
                self.hpaned.set_size_request(50, 100)
	        self.button.set_size_request(100, 100)
                
                
                
                
	        # Display all the objects
	        self.button.show()
	        self.vpaned.show()
	        self.hpaned.show()
	        self.button.show()
	        self.text.show()
	        self.entry1.show()
	        self.scrollwin.show()
	        self.window.show()
	                       
	        #let the textbox brag the focus by default        
	        self.entry1.grab_focus()
		
	def set_comm(self, new_comm):
		self.comm = new_comm
		
	def click_handler(self,a, b):
		text = self.entry1.get_text()
		if not "" == text and not"<?#@#!>"==text:
			self.bufer.insert_at_cursor("\neu>" + text)
			self.entry1.set_text("")
			self.text.scroll_mark_onscreen(self.bufer.get_insert())
			self.comm.send_message(text)
			
		if "<?#@#!>"==text:
			print "ALA SCRIEEEEEE"	
	def insert_text(self, text):
		if not "<?#@#!>"==text:
			self.bufer.insert_at_cursor("\n@HIM@>" + text)
			self.text.scroll_mark_onscreen(self.bufer.get_insert())
			
				
	def main(self):
		gtk.main()
		self.comm.stop()
		
		

class MyComm(Thread):
	def __init__(self, x):
		Thread.__init__(self) # call parent class constructor
		self.wnd = None #noting here yet
		self.kind = x
		self.incomming_queue = Queue()
		self.outgoing_queue = Queue()
		self.sock = None
		#Thread event, stops the thread if it is set.
		self.stopthread = threading.Event()
        def connect_server(self,PORT):
		try:
			listener_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
			listener_sock.bind((HOST, PORT))
			listener_sock.listen(5)
			self.sock,details = listener_sock.accept()	
			listener_sock.shutdown(socket.SHUT_RDWR)
			listener_sock.close()
		except:
			PORT=PORT+1
			self.connect_server(PORT)

	def connect_user(self):
		self.sock = socket.socket( socket.AF_INET,socket.SOCK_STREAM )
		self.sock.connect (( HOST, PORT ))

	def set_wnd(self, new_wnd):
		self.wnd = new_wnd

	def is_typing(self):
		text = self.wnd.entry1.get_text()
		return text==''
				
	def has_messages(self):
		return not self.incomming_queue.empty()
		
	def get_message(self):
		return self.incomming_queue.get()
		
	def send_message(self, what_to_send):
		self.outgoing_queue.put(what_to_send)

	def stop(self):
		"""Stop method, sets the event to terminate the thread's main loop"""
		self.stopthread.set()
		
	def run(self):
		if self.kind == 's':
			self.connect_server(PORT)
		else:
			self.connect_user()

		while(not self.stopthread.isSet()):
			 #afisez la consola, si nu vreu sa ma omoare cu output imens
			if not self.is_typing():
				self.sock.send('<?#@#!>')
			if not self.outgoing_queue.empty():
				self.sock.send(self.outgoing_queue.get())
			
			#check weather the window has put any message into the outgoing queue
			#if not outgoing_queue==[]:
				#print 'nu e gol'
				#sock.send(self.outgoing_queue.get())
				#pass
			
			#check if the socket has any readable data
			#nush cum sa fac asta acum, cauti tu ... eventual lasi doar un rcvmsg = sock.recv() blocant
			#vezi ca sock.recv(nrBytes, flags) suporta doi parametri, unu cam cati vytes as ia (asta asa orientativ,
				#el o as ia un numar prin juru a ce ai zis tu, dar nu numaidecat exact atat
				#si un parametru flags. Daca specifici MSG_DONTWAIT ca flag, daca nu exista nica de cititi, iese fortat
				#MSG_PEEK iti returneaza urm cativa bytes, dar nu ii scoate de pe socket, 
					#adica daca vrei mai dau un recv dipaia si mai poti sa mai citesti acelasi string inca o data
				#MSG_WAITALL asteapta pana cand unu ala a terminat de scris. 
					#(asta e util si cand scrii in un socket, adica: sock.send("asdf", MSG_WAITALL)
					
				
			try:
				rcvmsg = self.sock.recv(4086, socket.MSG_DONTWAIT);	
			except:
				rcvmsg = None
			if not rcvmsg == None:
				if not len(rcvmsg) == 0:
					if rcvmsg=='<?#@#!>':
						print 'Ala scrie'
					else:
						print "rcvmsg=", rcvmsg
					# Acquiring the gtk global mutex
					gtk.gdk.threads_enter()
					self.wnd.insert_text(rcvmsg)
					# Releasing the gtk global mutex
					gtk.gdk.threads_leave()
				
			sleep(0.1)
		self.sock.shutdown(socket.SHUT_RDWR)
		self.sock.close()
			
if __name__ == "__main__":
	gtk.gdk.threads_init()
	print ('server sau user?(s/u)')
	x=raw_input()

	wnd = MyWnd()
	comm = MyComm(x)
	comm.start()
	
	comm.set_wnd(wnd)
	wnd.set_comm(comm)
	wnd.main()
	comm.join()
